import type { Router } from 'vue-router';
import { whiteListRoutesNames } from './routes';
import { useAccessStore } from '@/store';
import { startProgress, stopProgress } from '@core/shared/utils';
import { preferences } from '@/core/preferences';
import { DEFAULT_HOME_PATH, LOGIN_PATH } from '@/constants';

/**
 * 通用守卫配置
 * @param router
 */
function setupCommonGuard(router: Router) {
  // 记录已经加载的页面
  const loadedPaths = new Set<string>();

  router.beforeEach(async (to) => {
    to.meta.loaded = loadedPaths.has(to.path);

    // 页面加载进度条
    if (!to.meta.loaded && preferences.transition.progress) {
      startProgress();
    }
    return true;
  });

  router.afterEach((to) => {
    // 记录页面是否加载,如果已经加载，后续的页面切换动画等效果不在重复执行

    loadedPaths.add(to.path);

    // 关闭页面加载进度条
    if (preferences.transition.progress) {
      stopProgress();
    }
  });
}

/**
 * 权限访问守卫配置
 * @param router
 */
function setupAccessGuard(router: Router) {
  router.beforeEach(async (to, from) => {
    const accessStore = useAccessStore();
    // 路由在白名单中的话可直接跳过
    if (whiteListRoutesNames.includes(to.name as string)) {
      if (to.path === LOGIN_PATH && accessStore.accessToken) {
        return decodeURIComponent(
          (to.query?.redirect as string) || DEFAULT_HOME_PATH,
        );
      }
      return true;
    }
    // 如果当前没有token
    if (!accessStore.accessToken) {
      // 如果跳转的不是登录页，跳转到登录页
      if (to.fullPath !== LOGIN_PATH) {
        return {
          path: LOGIN_PATH,
          // 携带当前跳转的页面，登录后重新跳转该页面
          query:
            to.fullPath === DEFAULT_HOME_PATH
              ? {}
              : { redirect: encodeURIComponent(to.fullPath) },
          replace: true,
        };
      }
      // 跳转的是登录页，放行
      return to;
    }
    // 如果已经生成过动态路由，放行
    if (accessStore.isAccessChecked) {
      return true;
    }
    // 否则开始生成动态路由
    await accessStore.generateRoutesByBackend();
    accessStore.accessRoutes.forEach((routeItem) => {
      router.addRoute(routeItem);
    });

    accessStore.setIsAccessChecked(true);
    const redirectPath = (from.query.redirect ??
      (to.path === DEFAULT_HOME_PATH
        ? DEFAULT_HOME_PATH
        : to.fullPath)) as string;

    return {
      ...router.resolve(decodeURIComponent(redirectPath)),
      replace: true,
    };
  });
}
export const createRouterGuard = (router: Router) => {
  setupCommonGuard(router);
  setupAccessGuard(router);
};
